package com.rednote.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rednote.common.JwtUtil;
import com.rednote.common.UserContextHolder;
import com.rednote.entity.*;
import com.rednote.entity.vo.UserProfileVO;
import com.rednote.mapper.*;
import com.rednote.service.UserFollowService;
import com.rednote.service.UsersService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户基本信息表(Users)服务实现类
 *
 * @author yao suxuan
 * @since 2025-05-24 17:50:50
 */
@Slf4j
@Service
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements UsersService {
    
    @Autowired
    private JwtUtil jwtUtil;
    
    @Autowired
    private UserRoleMapper userRoleMapper;
    
    @Autowired
    private RoleMapper roleMapper;
    
    @Autowired
    private RolePermissionMapper rolePermissionMapper;
    
    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private UserFollowMapper userFollowMapper;

    @Autowired
    private UserLikesMapper userLikesMapper;

    @Autowired
    private UserFollowService userFollowService;
    
    @Override
    public Users register(Users user) {
        // 检查账号是否已存在
        LambdaQueryWrapper<Users> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Users::getAccount, user.getAccount())
                .or()
                .eq(user.getEmail() != null, Users::getEmail, user.getEmail())
                .or()
                .eq(user.getPhone() != null, Users::getPhone, user.getPhone());
        
        Long count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            return null;
        }
        
        // 保存用户信息
        boolean saved = save(user);
        if (saved) {
            user.setPassword(null);
            return user;
        }
        return null;
    }
    
    @Override
    public Users login(String account, String password) {
        // 构建查询条件
        LambdaQueryWrapper<Users> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Users::getAccount, account)
                .or()
                .eq(Users::getEmail, account)
                .or()
                .eq(Users::getPhone, account);
        
        // 查询用户
        Users user = baseMapper.selectOne(queryWrapper);
        if (user == null) {
            return null;
        }
        
        // 验证密码
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (encoder.matches(password, user.getPassword())) {
            // 清除密码等敏感信息
            user.setPassword(null);
            return user;
        }
        
        return null;
    }

    @Override
    public UserProfileVO getUserInfo(Integer userId) {
        try {
            log.info("Attempting to get user info for userId: {}", userId);

            // 查询用户信息
            Users user = getById(userId);
            if (user == null) {
                log.warn("User not found for userId: {}", userId);
                return null;
            }

            // 查询关注和粉丝数
            Integer followCount = Math.toIntExact(userFollowMapper.selectCount(
                    new QueryWrapper<UserFollow>().eq("user_id", userId)));

            Integer fanCount = Math.toIntExact(userFollowMapper.selectCount(
                    new QueryWrapper<UserFollow>().eq("followed_user_id", userId)));

            // 查询获赞数
            Integer likedCount = Math.toIntExact(userLikesMapper.selectCount(
                    new QueryWrapper<UserLikes>().inSql("target_id",
                            "SELECT post_id FROM posts WHERE user_id = " + userId)
            ));

            UserProfileVO vo = new UserProfileVO();
            //如果不是本人，查询是否关注
            if(!Objects.equals(userId, UserContextHolder.getUserId())) {
                vo.setIsFollowed(userFollowService.isFollowed(userId));
            }
            vo.setUserId(user.getUserId());
            vo.setUsername(user.getUsername());
            vo.setAvatar(user.getAvatar());
            vo.setBio(user.getBio());
            vo.setGender(user.getGender());
            vo.setBirthday(user.getBirthday());
            vo.setPhone(user.getPhone());
            vo.setEmail(user.getEmail());
            vo.setStatus(user.getStatus());
            vo.setCreatedAt(user.getCreatedAt());

            vo.setFollowCount(followCount);
            vo.setFanCount(fanCount);
            vo.setLikedCount(likedCount);

            log.info("Successfully retrieved user profile for userId: {}", userId);
            return vo;
        } catch (Exception e) {
            log.error("Error getting user info: {}", e.getMessage(), e);
            return null;
        }
    }

    @Override
    public Users updateUserInfo(Integer userId, Users user) {
        try {
            log.info("Attempting to update user info for userId: {}", userId);

            // 获取原用户信息
            Users existingUser = getById(userId);
            if (existingUser == null) {
                log.warn("User not found for userId: {}", userId);
                return null;
            }

            // 设置不允许修改的字段
            user.setUserId(userId);
            user.setAccount(existingUser.getAccount());
            user.setPassword(existingUser.getPassword());
            user.setStatus(existingUser.getStatus());
            user.setCreatedAt(existingUser.getCreatedAt());

            // 验证邮箱和手机号是否被其他用户使用
            if (user.getEmail() != null && !user.getEmail().equals(existingUser.getEmail())) {
                LambdaQueryWrapper<Users> emailQuery = new LambdaQueryWrapper<>();
                emailQuery.eq(Users::getEmail, user.getEmail())
                        .ne(Users::getUserId, userId);
                if (baseMapper.selectCount(emailQuery) > 0) {
                    log.warn("Email already exists: {}", user.getEmail());
                    return null;
                }
            }

            if (user.getPhone() != null && !user.getPhone().equals(existingUser.getPhone())) {
                LambdaQueryWrapper<Users> phoneQuery = new LambdaQueryWrapper<>();
                phoneQuery.eq(Users::getPhone, user.getPhone())
                        .ne(Users::getUserId, userId);
                if (baseMapper.selectCount(phoneQuery) > 0) {
                    log.warn("Phone number already exists: {}", user.getPhone());
                    return null;
                }
            }

            // 更新用户信息
            boolean updated = updateById(user);
            if (!updated) {
                log.warn("Failed to update user info for userId: {}", userId);
                return null;
            }

            // 返回更新后的用户信息
            Users updatedUser = getById(userId);
            updatedUser.setPassword(null);
            log.info("Successfully updated user info for userId: {}", userId);
            return updatedUser;

        } catch (Exception e) {
            log.error("Error updating user info: {}", e.getMessage(), e);
            return null;
        }
    }

    @Override
    public List<String> getUserAuthorities(Integer userId) {
        Set<String> authorities = new HashSet<>();
        
        // 获取用户的角色
        List<UserRole> userRoles = userRoleMapper.selectList(
            new LambdaQueryWrapper<UserRole>()
                .eq(UserRole::getUserId, userId)
        );
        
        // 获取角色信息并添加角色权限
        for (UserRole userRole : userRoles) {
            Role role = roleMapper.selectById(userRole.getRoleId());
            if (role != null) {
                authorities.add("ROLE_" + role.getRoleId().toString());
                
                // 获取角色对应的权限
                List<RolePermission> rolePermissions = rolePermissionMapper.selectList(
                    new LambdaQueryWrapper<RolePermission>()
                        .eq(RolePermission::getRoleId, role.getRoleId())
                );
                
                // 添加权限
                for (RolePermission rolePermission : rolePermissions) {
                    Permission permission = permissionMapper.selectById(rolePermission.getPermissionId());
                    if (permission != null) {
                        authorities.add(permission.getPermissionId().toString());
                    }
                }
            }
        }
        
        return new ArrayList<>(authorities);
    }

    @Override
    public boolean updatePassword(String token, String oldPassword, String newPassword) {
        // 验证并解析token
        if (!jwtUtil.validateToken(token)) {
            log.warn("Token validation failed");
            return false;
        }

        try {
            // 从token中获取用户ID
            var claims = jwtUtil.parseToken(token);
            Integer userId = ((Number) claims.get("userId")).intValue();
            log.info("Attempting to update password for userId: {}", userId);

            // 获取原用户信息
            Users user = getById(userId);
            if (user == null) {
                log.warn("User not found for userId: {}", userId);
                return false;
            }

            // 验证旧密码
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            if (!encoder.matches(oldPassword, user.getPassword())) {
                log.warn("Old password is incorrect for userId: {}", userId);
                return false;
            }

            // 更新密码
            user.setPassword(encoder.encode(newPassword));
            boolean updated = updateById(user);
            if (!updated) {
                log.warn("Failed to update password for userId: {}", userId);
                return false;
            }

            log.info("Successfully updated password for userId: {}", userId);
            return true;
        } catch (Exception e) {
            log.error("Error updating password: {}", e.getMessage(), e);
            return false;
        }
    }
    
}
